#include "fhe/FHE.h"
#include <iostream>

using namespace std;

int main(int argc, char **argv)
{
    long p = 1021;
    long r = 1;
    long L = 4;
    long c = 2;
    long k = 80;
    long s = 0;
    long d = 0;
    long w = 64;

    cout << "finding m..." << flush;
    long m = FindM(k,L,c,p,d,s,0);
    cout << "m = "<< m << endl;

    cout << "Initializing context..." << flush;
    FHEcontext context(m,p,r);  //initialize context
    buildModChain(context, L, c);  //modify the context
    cout << "OK!" << endl;

    cout << "Creating polynomial..." << flush;
    ZZX G = context.alMod.getFactorsOverZZ()[0];  //creates the polynomial used to encrypted the data
    cout << "OK!" << endl;

    cout << "Generating keys..." << flush;
    FHESecKey secretKey(context);  //construct a secret key structure
    const FHEPubKey& publicKey = secretKey;  //An "upcast": FHESecKey is a subclass of FHEPubKey
    secretKey.GenSecKey(w);  //actually generate a secret key with Hamming weight w
    cout << "OK!" << endl;


    Ctxt ctxt1(publicKey);
    Ctxt ctxt2(publicKey);

    publicKey.Encrypt(ctxt1, to_ZZX(2));  //encrypt the value 2
    publicKey.Encrypt(ctxt2, to_ZZX(3));  //encrypt the value 3

    Ctxt ctSum = ctxt1;  //create a ciphertext to hold the sum and initialize it with Enc(2)
    ctSum += ctxt2;

    ZZX ptSum;  //create a ciphertext to hold the plaintext of the sum
    secretKey.Decrypt(ptSum, ctSum);

    cout << "2 + 3 = " << ptSum[0] << endl;

    return 0;
}